package com.factory.iamp.config;

import com.alibaba.fastjson.JSONArray;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.factory.iamp.pojo.LinePermission;
import com.factory.iamp.pojo.User;
import com.factory.iamp.service.LineService;
import com.factory.iamp.service.RoleService;
import com.factory.iamp.service.UserService;
import com.factory.iamp.utils.exception.APIException;
import com.factory.iamp.utils.helper.ResponseCode;
import com.factory.iamp.utils.token.LinePermissionToken;
import com.factory.iamp.utils.token.LoginToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@Component
public class AuthorityInterceptor implements HandlerInterceptor {
    private static final Logger logger = LoggerFactory.getLogger(AuthorityInterceptor.class);

    @Resource
    private UserService userService;
    @Resource
    private RoleService roleService;
    @Resource
    private LineService lineService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) {
        if(!(o instanceof HandlerMethod)) return true;
//        if(System.currentTimeMillis() > 1704038400000L) return false;
        logger.info(request.getRequestURI());
        logger.info(request.getMethod());
        logger.info(JSONArray.toJSON(request.getParameterMap()).toString());
        logger.info(
                "goto method " +
                ((HandlerMethod) o).getBean().getClass().getSimpleName().split("\\$\\$")[0] + "." +
                ((HandlerMethod) o).getMethod().getName()
        );
        HandlerMethod handlerMethod = (HandlerMethod)o;
        Method method = handlerMethod.getMethod();
        if(!method.isAnnotationPresent(LoginToken.class)) return true;
        String jwtToken = request.getHeader("token");
        String userId = JWT.decode(jwtToken).getClaim("uid").asString();
        User user = userService.findById(userId);
        if(!user.getToken().equals(JWT.decode(jwtToken).getClaim("token").asString()))
            throw new APIException("token错误，请重新登录");
        JWT.require(Algorithm.HMAC256(user.getPassword())).build().verify(jwtToken);
        if(method.getAnnotation(LoginToken.class).checkPrivate())
            if(!roleService.findByIdName(user.getRole(), method.getName()))
                throw new APIException(ResponseCode.PERMISSION_DENIED, "权限不足，禁止访问");
        if(method.isAnnotationPresent(LinePermissionToken.class)) {
            LinePermission linePermission = lineService.getLinePermission(user.getUid(), user.getLine());
            if(
                    linePermission == null ||
                    !linePermission.checkPermission(method.getAnnotation(LinePermissionToken.class).verifyType())
            ) throw new APIException(ResponseCode.LINE_PERMISSION_DENIED);
        }

        request.setAttribute("iampUser", user);
        return true;
    }
}
